package com.ysd.shopcar.utils;

import org.apache.commons.codec.binary.Hex;

import java.security.MessageDigest;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

/**
 * @author majl
 * @date 2019-5-24
 */
public class Md5Util {
    //16进制
    public static final char[] HEX_ARRAY = new char[]{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

    /**
     * 盐的位置
     */
    private static final Set<Integer> SALT_INDEX_SET = new HashSet<Integer>(){{
        int[] indexs = new int[]{0,4,6,7,9,11,17,18,22,29,32,35,40,42,45,47};
        for (int i =0 ; i< indexs.length;i++){
            add(indexs[i]);
        }
    }};

    public static void main(String[] args) {
        String pwd = "123456sS";
        String pwdMd5 = encodeMd5WithRandomSalt(pwd);
        System.out.println(pwdMd5);
        System.out.println(verifyMd5WithRandomSalt(pwd,pwdMd5));
    }

    /**
     * 密码做md5并加入随机盐
     * @param pwd
     * @return
     */
    public static String encodeMd5WithRandomSalt(String pwd) {
        String salt = genRandomStr();
        char[] result = new char[48];
        char[] pwdMd5 = md5Hex(pwd + salt).toCharArray();
        char[] saltArray = salt.toCharArray();
        for (int i = 0,pwdIndex = 0,saltIndex = 0; i < 48; i ++) {
            if(SALT_INDEX_SET.contains(i)){
                result[i] = saltArray[saltIndex++];
            }else {
                result[i] = pwdMd5[pwdIndex++];
            }
        }
        return new String(result);
    }

    /**
     * 生成16位随机的16进制字符串
     * @return
     */
    private static String genRandomStr(){
        StringBuilder sb = new StringBuilder();
        String[] arr = new String[16];
        for(int i = 0 ; i < 16; i++){
            sb.append(HEX_ARRAY[new Random().nextInt(16)]);
        }
        return sb.toString();
    }
    /**
     * 校验密码是否正确
     */
    public static boolean verifyMd5WithRandomSalt(String pwd, String md5) {
        if(pwd == null || "".equals(pwd)){
            return false;
        }
        if(md5 == null || md5.length() != 48){
            return false;
        }
        char[] pwdMd5 = new char[32];
        char[] saltArray = new char[16];
        char[] resultArray = md5.toCharArray();
        for (int i = 0,pwdIndex = 0,saltIndex = 0; i < 48; i++) {
            if(SALT_INDEX_SET.contains(i)){
                saltArray[saltIndex++] = resultArray[i];
            }else{
                pwdMd5[pwdIndex++] = resultArray[i];
            }
        }
        String salt = new String(saltArray);
        return md5Hex(pwd + salt).equals(new String(pwdMd5));
    }
    /**
     * 获取十六进制字符串形式的MD5摘要
     */
    public static String md5Hex(String src) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bs = md5.digest(src.getBytes());
            return new String(new Hex().encode(bs));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
